package com.googlecode.agscrum.model.entity;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.hibernate.annotations.Cascade;
import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.beans.factory.annotation.Configurable;

import com.googlecode.agscrum.model.service.Service;
import com.googlecode.agscrum.model.util.Criteria;
import com.googlecode.agscrum.model.util.Restrictions;
import com.googlecode.agscrum.model.validator.ValidatorUtil;

@Entity
@Configurable(autowire = Autowire.BY_NAME)
@Table(name = "tb_item")
public class Item {
	@Id
	@GeneratedValue(generator = "item_sequence", strategy = GenerationType.SEQUENCE)
	@SequenceGenerator(name = "item_sequence", sequenceName = "item_sequence")
	@Column(name = "id_item")
	private Long id;

	@Column(length = 70, nullable = false)
	private String name;
	@Column(length = 500)
	private String description;
	@Column(name = "ITEM_ORDER")
	private Integer order;

	private Integer estimate;

	@ManyToOne
	@JoinColumn(name = "id_product")
	private Product product;

	@ManyToOne
	@JoinColumn(name = "id_sprint")
	private Sprint sprint;

	@OneToMany(cascade = CascadeType.ALL,mappedBy="item")
	@JoinColumn(name = "id_item")
	@Cascade(value = org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
	private List<Task> tasks;

	@Transient
	private ValidatorUtil validatorUtil;

	public void setValidatorUtil(ValidatorUtil validatorUtil) {
		this.validatorUtil = validatorUtil;
	}

	@Transient
	private Service<Status, Long> statusService;

	public void setStatusService(Service<Status, Long> statusService) {
		this.statusService = statusService;
	}

	public void saveTask(Task task) {
		if (getTasks() == null) {
			setTasks(new ArrayList<Task>());
		}
		if (task.getId() == null) {
			if (task.getStatus() == null) {
				Criteria criteria = Criteria.getInstance("Status.searchQuery",
						Status.class);
				criteria.addAnd(Restrictions.eq("s.order", 1));
				List<Status> status = statusService.readByCriteria(criteria);
				if (status != null && status.size() > 0) {
					task.setStatus(status.get(0));
				}
			}
			task.setItem(this);
			validatorUtil.validate(task);
			tasks.add(task);
		} else {
			validatorUtil.validate(task);
			if (tasks.contains(task)) {
				tasks.set(tasks.indexOf(task), task);
			}
		}
	}

	public void removeTask(Task task) {
		if (tasks != null) {
			if (tasks.contains(task)) {
				tasks.remove(task);
			}
		}
	}

	public boolean hasEstimate() {
		if (getEstimate() < 1)
			return false;
		else
			return true;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public Long getId() {
		return id;
	}

	public void setProduct(Product product) {
		this.product = product;
	}

	public Product getProduct() {
		return product;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public String getDescription() {
		return description;
	}

	public void setEstimate(Integer estimate) {
		this.estimate = estimate;
	}

	public Integer getEstimate() {
		return estimate;
	}

	public void setTasks(List<Task> tasks) {
		this.tasks = tasks;
	}

	public List<Task> getTasks() {
		return tasks;
	}

	public void setSprint(Sprint sprint) {
		this.sprint = sprint;
	}

	public Sprint getSprint() {
		return sprint;
	}

	public List<Task> getTasks(Status status) {
		List<Task> tasksFilter = new ArrayList<Task>();
		for (Task task : tasks) {
			if (status.equals(task.getStatus())) {
				tasksFilter.add(task);
			}
		}
		return tasksFilter;
	}

	public boolean changeStatusTask(Item item, Task taskParam, Status status) {
		for (Task task : getTasks()) {
			if (task.equals(taskParam)) {
				task.setStatus(status);
				return true;
			}
		}
		return false;
	}

	public boolean isDone() {
		if (tasks != null) {
			for (Task task : tasks) {
				if (!Long.valueOf(4).equals(task.getStatus().getId())) {
					return false;
				}
			}
		} else {
			return false;
		}
		return true;
	}
}
